package win.liumian.sso.server.service;

import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import win.liumian.sso.server.conf.JwtConfig;
import win.liumian.sso.server.dao.mapper.ClientMapper;
import win.liumian.sso.server.dao.mapper.TicketMapper;
import win.liumian.sso.server.dao.po.Client;
import win.liumian.sso.server.dao.po.Ticket;
import win.liumian.sso.server.dao.po.TicketExample;
import win.liumian.sso.server.dao.po.User;
import win.liumian.sso.server.util.JwtHelper;

import java.util.Date;

@Service
public class TicketService {

    private Logger logger = LoggerFactory.getLogger(TicketService.class);

    @Autowired
    private JwtConfig jwtConfig;

    @Autowired
    private TicketMapper ticketMapper;

    @Autowired
    private ClientMapper clientMapper;


    @Autowired
    private RedisService redisService;


    public String newLoginTicket(User user, String clientId) {

        TicketExample updateExample = new TicketExample();
        updateExample.createCriteria().andUseridEqualTo(user.getId()).andDeletedEqualTo(false);

        Ticket updateTicket = new Ticket();
        updateTicket.setDeleted(true);
        ticketMapper.updateByExampleSelective(updateTicket, updateExample);

        String jwt = JwtHelper.createJWT(String.valueOf(user.getId()), jwtConfig.getExpiresMills(), jwtConfig.getBase64Secret());

        Ticket ticket = new Ticket();
        ticket.setSsoticket(jwt);
        ticket.setClientid(Long.valueOf(clientId));
        ticket.setUserid(user.getId());
        ticket.setDeleted(false);

        ticketMapper.insert(ticket);

        return jwt;
    }

    /**
     * 判断登录凭证是否有效
     * @param ssoTicket 登录凭证
     * @return
     */
    public boolean isLegalTicket(String ssoTicket) {

        //判断该凭证是否在redis中存在，若存在说明该凭证无效
        if (redisService.exists(ssoTicket)) {
            return false;
        }
        //尝试对登录凭证进行解析
        Claims claims = JwtHelper.parseJWT(ssoTicket, jwtConfig.getBase64Secret());
        if (ObjectUtils.isEmpty(claims)) {
            //解析失败，将该凭证放入redis，标记为失效凭证
            redisService.set(ssoTicket, "null", jwtConfig.getExpiresMills());
            return false;
        } else {
            //解析成功，直接返回true
            return true;
        }
    }


    /**
     * 注销登录凭证
     * @param ssoTicket 登录凭证
     */
    public void deleteTicket(String ssoTicket) {

        //尝试解析，即检查是否是合法的JWT格式
        Claims claims = JwtHelper.parseJWT(ssoTicket, jwtConfig.getBase64Secret());
        if (ObjectUtils.isEmpty(claims)) {
            return;
        }

        //将该登录凭证放入redis中，进行标记，过期时间为JWT的过期时间
        String userId = claims.get("userId", String.class);
        redisService.set(ssoTicket, userId, jwtConfig.getExpiresMills());

        //在数据库中将该凭证设置成失效状态
        TicketExample updateExample = new TicketExample();
        updateExample.createCriteria().andSsoticketEqualTo(ssoTicket).andDeletedEqualTo(false);
        Ticket updateTicket = new Ticket();
        updateTicket.setDeleted(true);
        ticketMapper.updateByExampleSelective(updateTicket, updateExample);
    }

    public Client getClient(String clientId) {

        long l;
        try {
            l = Long.parseLong(clientId);
        } catch (NumberFormatException e) {
            logger.info("解析clientId失败");
            return null;
        }
        return clientMapper.selectByPrimaryKey(l);

    }


}
